﻿#include "PrimitivesBox.h"
// core
#include "FITK_Kernel/FITKCore/FITKDataRepo.h"
#include "FITK_Kernel/FITKCore/FITKOperatorRepo.h"
//framework
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
//python
#include "FITK_Kernel/FITKPython/FITKPythonInterface.h"
//operator
#include "OperatorsInterface/GraphEventOperator.h"
#include "FITK_Kernel/FITKCore/FITKActionOperator.h"

//interface
#include "FITK_Interface/FITKInterfaceGeometry/FITKGeoCommandList.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKGeoInterfaceFactory.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelBox.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelSphere.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoMultiDelete.h"
//component
#include "FITK_Component/FITKGeoCompOCC/FITKOCCModelSolid.h"
#include "FITK_Component/FITKGeoCompOCC/FITKOCCModelOperSolid.h"
#include <QMetaEnum>
#include <QDebug>

Box::Box(int id /*= 0*/)
{
    if (id == 0) return;
    m_command = wTools.getGeoCommand("FGTBox");
    if (!m_command) wTools.updateExecutionStatus(false);
    else m_box = dynamic_cast<Interface::FITKAbsGeoModelBox*>(m_command);
}

Box::Box(Interface::FITKAbsGeoModelBox* box)
{
    m_command = m_box = box;
}

const QString Box::getClassName()
{
    return "Box";
}

bool Box::setPoint1(QList<double> p1)
{
    if (m_box == nullptr) return false;
    double arg1[3]{ p1[0], p1[1], p1[2] };
    m_box->setPoint1(arg1);
    return true;
}

bool Box::setPoint2(QList<double> p2)
{
    if (m_box == nullptr) return false;
    double arg1[3];
    double arg2[3]{ p2[0], p2[1], p2[2] };
    m_box->getPoint1(arg1);
    double len[3] = { std::abs(arg1[0] - arg2[0]), std::abs(arg1[1] - arg2[1]), std::abs(arg1[2] - arg2[2]) };
    m_box->setLength(len);
    return true;
}

bool Box::setDimensions(QList<double> dimensions)
{
    if (m_box == nullptr) return false;
    double arg2[3]{ dimensions[0], dimensions[1], dimensions[2] };
    m_box->setLength(arg2);
    return true;
}

Box* BoxWrapper::new_Box()
{
    return new Box(-1);
}

void BoxWrapper::deleteCmd(Box* obj)
{
    if (!obj) return;
    auto command = obj->getCommand();
    if (!geoCmdUndoList->isContains(command) && !geoCmdRedoList->isContains(command)) delete_Box(obj);
    else if (command->getCommandStatus() == Interface::FITKGeoEnum::FITKGeoStatus::FGSNormal)
    {

        // 创建移除指令。
        auto removeCommand = wTools.getGeoCommand("FGTMultiDelete");
        auto deleteCmd = dynamic_cast<Interface::FITKAbsGeoMultiDelete*>(removeCommand);
        if (!deleteCmd) return;

        deleteCmd->setDataObjectName(geoCmdUndoList->checkName(QString("Delete-%1").arg(geoCmdUndoList->getDataCount())));

        QList<Interface::FITKAbsGeoCommand*> refedCmdList = obj->getCommand()->getDownStreamCommands();

        QList<int> ids;
        for (Interface::FITKAbsGeoCommand* refedCmd : refedCmdList)
        {
            if (refedCmd)
            {
                ids.push_back(refedCmd->getDataObjectID());
            }
        }

        // 设置被移除命令ID列表并添加至命令列表。
        deleteCmd->setDeleteCommandIDs(ids);
        bool flag = deleteCmd->update();
        wTools.updateExecutionStatus(flag);
        if (flag)
            geoCmdUndoList->appendDataObj(deleteCmd);
        else
            delete deleteCmd;

        updateUI(deleteCmd->getDataObjectID());
    }
    updateUI(-1);
}

void BoxWrapper::delete_Box(Box* obj)
{
    if (obj) delete obj;
}

void BoxWrapper::setPoint1(Box* obj, QList<double> p1)
{
    obj->setPoint1(p1);
}

void BoxWrapper::setPoint2(Box* obj, QList<double> p2)
{
    obj->setPoint2(p2);
}

void BoxWrapper::setDimensions(Box* obj, QList<double> dimensions)
{
    obj->setDimensions(dimensions);
}

void BoxWrapper::setPoints(Box* obj, QList<double> p1, QList<double> p2)
{
    obj->setPoint1(p1);
    obj->setPoint2(p2);
}

void BoxWrapper::update(Box* obj)
{
    bool flag = obj->update();
    wTools.updateExecutionStatus(flag);

    obj->getCommand()->setDataObjectName(geoCmdUndoList->checkName(QString("Box-%1").arg(geoCmdUndoList->getDataCount() + 1)));

    if (flag)
    {
        geoCmdUndoList->appendDataObj(obj->getCommand());
        registerSig(obj, obj->getCommand()->getDataObjectID(), "delete");
        updateUI(obj->getCommand()->getDataObjectID());
    }
}

Box* BoxWrapper::static_Box_Create()
{
    return new_Box();
}
